﻿#ifndef __AVOID_CONTROL_CTL_HELP_DHSOI_HEAD_FILE_INCLUDED__
#define __AVOID_CONTROL_CTL_HELP_DHSOI_HEAD_FILE_INCLUDED__
#include "ctlDefine.h"
#include "ctlText.h"
#include "ctlColorDefine.h"
#include <string>

namespace swui
{
	template<typename DeleteClass, size_t Number = 1>
	struct ctlDestructor
	{
		static void deleter(void* ptr)
		{
			DeleteClass* begin = reinterpret_cast<DeleteClass*>(ptr);
			for(size_t i = 0; i != Number; ++i, ++begin)
				begin->~DeleteClass();
		}
	};
	namespace ctlListSortFunc
	{
		// 采用 std::wcscmp
		bool charAscending(
			std::wstring::const_pointer a,
			std::wstring::const_pointer b);
		/* 若字符串的前缀无法解析成数字
		 * 则视为 std::numeric_limits<long>::min()
		 * 若字符串的前缀可以解析成数字
		 * 则使用解析成的数字 */
		bool longAscending(
			std::wstring::const_pointer a,
			std::wstring::const_pointer b);
		// 解析为二进制有符号数
		bool binAscending(
			std::wstring::const_pointer a,
			std::wstring::const_pointer b);
		// 解析为二进制无符号数
		bool ubinAscending(
			std::wstring::const_pointer a,
			std::wstring::const_pointer b);
		inline bool charDescending(
			std::wstring::const_pointer a,
			std::wstring::const_pointer b)
		{
			return !charAscending(a, b);
		}
		inline bool longDescending(
			std::wstring::const_pointer a,
			std::wstring::const_pointer b)
		{
			return !longAscending(a, b);
		}
		inline bool binDescending(
			std::wstring::const_pointer a,
			std::wstring::const_pointer b)
		{
			return !binAscending(a, b);
		}
		inline bool ubinDescending(
			std::wstring::const_pointer a,
			std::wstring::const_pointer b)
		{
			return !ubinAscending(a, b);
		}
	}
	namespace ctlPreDefineText
	{
		const std::wstring::const_pointer digit = L"1234567890";
		const std::wstring::const_pointer hexDigit = L"1234567890abcdefABCDEF";
		const std::wstring::const_pointer octDigit = L"12345670";
		const std::wstring::const_pointer binDigit = L"10";
		const std::wstring::const_pointer alpha = L"abcdefghijklmnopqrstuvwxyz"
			L"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		const std::wstring::const_pointer alphaDigit = L"abcdefghijklmnopqrstuvwxyz"
			L"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
		const std::wstring::const_pointer lowerAlpha = L"abcdefghijklmnopqrstuvwxyz";
		const std::wstring::const_pointer upperAlpha = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		const std::wstring::const_pointer digitSpace = L"1234567890\n\r \t";
		const std::wstring::const_pointer hexDigitSpace = L"1234567890abcdefABCDEF\n\r \t";
		const std::wstring::const_pointer octDigitSpace = L"12345670\n\r \t";
		const std::wstring::const_pointer binDigitSpace = L"10\n\r \t";
		const std::wstring::const_pointer alphaSpace = L"abcdefghijklmnopqrstuvwxyz"
			L"ABCDEFGHIJKLMNOPQRSTUVWXYZ\n\r \t";
		const std::wstring::const_pointer alphaDigitSpace = L"abcdefghijklmnopqrstuvwxyz"
			L"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\n\r \t";
		const std::wstring::const_pointer lowerAlphaSpace = L"abcdefghijklmnopqrstuvwxyz\n\r \t";
		const std::wstring::const_pointer upperAlphaSpace = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ\n\r \t";
	}

	inline ctlRectTemplate<float> 
		Absolute2Percent(const ctlRect& rect, const ctlRect& parent)
	{
		return ctlRectTemplate<float>(
			(float)rect.x / (float)parent.cx, 
			(float)rect.y / (float)parent.cy, 
			(float)rect.cx / (float)parent.cx, 
			(float)rect.cy / (float)parent.cy);
	}
	inline ctlRect Percent2Absolute(
		const ctlRectTemplate<float>& rect, const ctlRect& parent)
	{
		return ctlRect(
			int(rect.x * parent.cx), 
			int(rect.y * parent.cy), 
			int(rect.cx * parent.cx), 
			int(rect.cy * parent.cy));
	}
	inline int ctlMax(int a, int b) { return a > b ? a : b; }
	inline int ctlMin(int a, int b) { return a < b ? a : b; }

	template<typename EnumType> inline
	EnumType enumTypeAnd(EnumType a, EnumType b)
	{
		return static_cast<EnumType>(
			static_cast<unsigned>(a) & 
			static_cast<unsigned>(b));
	}
	template<typename EnumType> inline
	EnumType enumTypeOr(EnumType a, EnumType b)
	{
		return static_cast<EnumType>(
			static_cast<unsigned>(a) | 
			static_cast<unsigned>(b));
	}
	template<typename EnumType> inline
	bool enumTypeAndIsNull(EnumType a, EnumType b)
	{
		return 0 == (static_cast<unsigned>(a) & 
			static_cast<unsigned>(b));
	}


	inline ctlStyleGradient* getStyleGradient(ctlStyleBase* style)
	{
		if(style->styleType == ctlStyleType::gradient)
			return (ctlStyleGradient*)style;
		return nullptr;
	}
	inline const ctlStyleGradient* getStyleGradient(const ctlStyleBase* style)
	{
		if(style->styleType == ctlStyleType::gradient)
			return (ctlStyleGradient*)style;
		return nullptr;
	}
	inline ctlStyleSolid* getStyleSolid(ctlStyleBase* style)
	{
		if(style->styleType == ctlStyleType::solid)
			return (ctlStyleSolid*)style;
		return nullptr;
	}
	inline const ctlStyleSolid* getStyleSolid(const ctlStyleBase* style)
	{
		if(style->styleType == ctlStyleType::solid)
			return (ctlStyleSolid*)style;
		return nullptr;
	}
}

#endif